import io
import datetime
import pandas as pd

from django.db.models import Count
from django.http import HttpResponse
from rest_framework.permissions import IsAuthenticated

from common.tdengine import load_tdengine_pool
from dvadmin.system.models import Dept, Role
from dvadmin.utils.filters import DataLevelPermissionsFilter
from dvadmin.utils.json_response import DetailResponse
from iot_api.base import ret_res
from rest_framework.generics import GenericAPIView
from iot.models import Point, Cabinet, Warn, Gradation
from iot_api.select import get_point_data, get_warn_and_early_warn, get_warn, applet_warning
from iot_api.serializers import CabinetSerializer, PointSerializer
import logging


logger = logging.getLogger(__name__)
TEMP_TYPE = 'T'
VOLTAGE_TYPE = 'v'
WARN_TYPE = 1
EARLY_WARN_TYPE = 0
DESCRIPOTION = 'sum'


class CabinetListView(GenericAPIView):
    queryset = Cabinet.objects.all()
    serializer_class = CabinetSerializer
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        cabinet = self.filter_queryset(self.get_queryset())
        serializer = self.get_serializer(cabinet, many=True)
        return ret_res(data=serializer.data)


class CabinetPointView(GenericAPIView):
    queryset = Point.objects.all()
    serializer_class = PointSerializer
    # permission_classes = [IsAuthenticated]
    permission_classes = []

    def get(self, request, *args, **kwargs):
        queryset = self.get_queryset()
        cabinet_id = request.query_params.get('cabinetId')
        point_type = request.query_params.get('pointType')
        if not point_type:
            point_type = TEMP_TYPE
        if not cabinet_id:
            cabinet_id = Cabinet.objects.first().id
        instance = queryset.filter(cabinet__id=cabinet_id).filter(unit__type=point_type)
        serializer = self.get_serializer(instance, many=True)
        return ret_res(data=serializer.data)


class PointDetailView(GenericAPIView):
    queryset = Point.objects.all()
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        queryset = self.get_queryset()
        point_code = request.query_params.get('pointCode')
        print(point_code)
        name = queryset.filter(code=point_code).first().name
        start = request.query_params.get('startTime')
        end = request.query_params.get('endTime')
        time = datetime.datetime.now()
        if start:
            start = start + ' 00:00:00'
        if end:
            end = end + ' 23:59:59'
        if not start:
            start = time - datetime.timedelta(hours=1)
        if not end:
            end = time
        data = get_point_data(name, point_code, start, end)
        return ret_res(code=0, data=data)


class PointLimitView(GenericAPIView):
    queryset = Point.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        point_type = request.query_params.get('pointType')
        points = ''
        if point_type == TEMP_TYPE:
            points = queryset.filter(unit__type=point_type).order_by('-value')[0:4]
        if point_type == VOLTAGE_TYPE:
            points = queryset.filter(unit__type=point_type).order_by('value')[0:4]
        data = [
            {
                'cabinet': each.cabinet.name,
                'name': each.name,
                'value': each.value,
                'is_warning': each.is_warning,
                'time': datetime.datetime.strftime(each.update_datetime, '%Y-%m-%d %H:%M:%S')
            }
            for each in points
        ]
        return ret_res(data=data)


class WarnLimitView(GenericAPIView):
    queryset = Warn.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        warn_type = request.query_params.get('warnType')
        point_type = request.query_params.get('pointType')
        if not point_type:
            point_type = TEMP_TYPE
        warns = queryset.filter(type=warn_type).filter(point__unit__type=point_type).order_by('-create_datetime')[0:8]
        data = [
            {
                'id': each.id,
                'cabinet': each.point.cabinet.name,
                'point': each.point.name,
                'value': each.value,
                'is_handel': each.is_handel,
                'time': datetime.datetime.strftime(each.create_datetime, '%Y-%m-%d %H:%M:%S')
            }
            for each in warns
        ]
        return ret_res(code=0, data=data)


class OnlineCountView(GenericAPIView):
    queryset = Point.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        points = self.filter_queryset(self.get_queryset())
        data = dict()
        data['cabinet_count'] = len(set(points.filter().values_list('cabinet__id', flat=True)))
        data['temp_count'] = points.filter(unit__type=TEMP_TYPE).count()
        data['v_count'] = points.filter(unit__type=VOLTAGE_TYPE).count()
        return ret_res(code=0, data=data)


class WarnCountView(GenericAPIView):
    queryset = Point.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        warn = self.filter_queryset(self.get_queryset()).filter(is_warning=WARN_TYPE)
        data = dict()
        # time = datetime.datetime.now()
        # start = time-datetime.timedelta(minutes=3).filter(create_datetime__gte=start)
        data['cabinet_count'] = warn.values('cabinet__id').annotate(count=Count('cabinet__id')).count()
        data['temp_count'] = warn.filter(unit__type=TEMP_TYPE).count()
        data['v_count'] = warn.filter(unit__type=VOLTAGE_TYPE).count()
        return ret_res(code=0, data=data)


class WarnCabinetView(GenericAPIView):
    queryset = Warn.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        point_type = request.query_params.get('pointType')
        if not point_type:
            point_type = TEMP_TYPE
        warn = self.filter_queryset(self.get_queryset()).filter(point__unit__type=point_type)
        time = datetime.datetime.now()
        start = datetime.datetime(year=time.year, month=time.month, day=time.day, hour=0, minute=0, second=0)
        warn_count = warn.filter(type=WARN_TYPE).filter(create_datetime__gte=start).count()
        early_warn_count = warn.filter(type=EARLY_WARN_TYPE).filter(create_datetime__gte=start).count()
        warn_cabinet_count = len(set(warn.filter(type=WARN_TYPE).filter(create_datetime__gte=start).
                                     values_list('point__cabinet__id', flat=True)))
        early_warn_cabinet_count = len(set(warn.filter(type=EARLY_WARN_TYPE).filter(create_datetime__gte=start).
                                           values_list('point__cabinet__id', flat=True)))
        return ret_res(code=0, data={'early_warn_count': early_warn_count, 'warn_cabinet_count': warn_cabinet_count,
                                     'warn_count': warn_count,  'early_warn_cabinet_count': early_warn_cabinet_count})


class WarnCabinetSortView(GenericAPIView):
    queryset = Warn.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        point_type = request.query_params.get('pointType')
        if not point_type:
            point_type = TEMP_TYPE
        queryset = self.filter_queryset(self.get_queryset()).filter(type=WARN_TYPE).filter(point__unit__type=point_type)
        start = datetime.datetime.now()-datetime.timedelta(days=30)
        cab = queryset.filter(create_datetime__gte=start).values('point__cabinet__name').annotate(
            count=Count('point__cabinet__name')).order_by('-count')[:5]
        count_list = []
        name_list = []
        for each in cab:
            count_list.append(each['count'])
            name_list.append(each['point__cabinet__name'])
        data = {'count_list': count_list, 'name_list': name_list}
        return ret_res(code=0, data=data)


class WarnPointSortView(GenericAPIView):
    queryset = Warn.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        point_type = request.query_params.get('pointType')
        if not point_type:
            point_type = TEMP_TYPE
        queryset = self.filter_queryset(self.get_queryset()).filter(type=WARN_TYPE).filter(point__unit__type=point_type)
        end = datetime.datetime.now()
        start = end-datetime.timedelta(days=30)
        cab_count = queryset.filter(create_datetime__gte=start).values('point__id').annotate(
            count=Count('point__id')).order_by('-count')[:5]
        count_list = []
        name_list = []
        for each in cab_count:
            count_list.append(each['count'])
            point_id = each['point__id']
            point = Point.objects.filter(id=point_id).first()
            name = point.cabinet.name+point.name
            name_list.append(name)
        data = {'count_list': count_list, 'name_list': name_list}
        return ret_res(code=0, data=data)


class WarnPointLineView(GenericAPIView):
    # filter_backends = [DataLevelPermissionsFilter]
    queryset = Warn.objects.all()
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        queryset = self.get_queryset().filter(type=WARN_TYPE).filter(point__unit__type=TEMP_TYPE)
        time = datetime.datetime.now()
        point_code = request.query_params.get('pointCode')
        start = datetime.datetime(year=time.year, month=time.month, day=time.day, hour=0, minute=0, second=0)
        warns = queryset.filter(create_datetime__gte=start).filter(point__code=point_code).all()
        data = dict()
        time_list = []
        value_list = []
        for each in warns:
            time_list.append(datetime.datetime.strftime(each.create_datetime, '%Y-%m-%d %H:%M:%S'))
            value_list.append(each.value)
        data['time_list'] = time_list
        data['value_list'] = value_list
        return ret_res(code=0, data=data)

# 返回全部的电站 和id
class RoomView(GenericAPIView):
    queryset = Cabinet.objects.all()
    # permission_classes = [IsAuthenticated]
    # filter_backends = [DataLevelPermissionsFilter]
    permission_classes = []
    filter_backends = []

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        rooms = queryset.filter().values('dept__id').order_by('dept__id').annotate(name=Count('dept__id'))
        data = [
            {
                'deptId': room['dept__id'],
                'name': Dept.objects.filter(id=room['dept__id']).first().name
            }
            for room in rooms
        ]
        return ret_res(code=0, data=data)


# 接收一个deptid，返回该id下全部的信息
class RoomDetailView(GenericAPIView):
    queryset = Cabinet.objects.all()
    # permission_classes = [IsAuthenticated]
    # filter_backends = [DataLevelPermissionsFilter]
    permission_classes = []
    filter_backends = []
    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        dept_id = request.query_params.get('deptId')
        point_type = request.query_params.get('pointType')
        if point_type:
            pass
        else:
            point_type = TEMP_TYPE
        cabinets = queryset.filter(dept__id=dept_id).order_by('create_datetime')
        data = []
        for cabinet in cabinets:
            points = Point.objects.filter(cabinet=cabinet.id).filter(unit__type=point_type).order_by('gradation__id')
            if points:
                cabinet_dict = {}
                points_data = []
                cabinet_dict['cabinetName'] = cabinet.name
                cabinet_dict['cabinetId'] = cabinet.id
                cabinet_dict['warn_value'] = cabinet.warm_warning
                cabinet_dict['early_warn_value'] = cabinet.warm_early_warning
                cabinet_dict['status'] = '正常'
                gradations = points.values('gradation__name').annotate(count=Count('gradation__name'))
                for gradation in gradations:
                    gradation_name = gradation['gradation__name']
                    gradation_data = {'gradation': gradation_name}
                    point = points.filter(gradation__name=gradation_name).all()
                    for each in point:
                        class_name = each.code[-1]
                        gradation_data[class_name] = each.value
                        if cabinet_dict['status'] == '正常' or cabinet_dict['status'] == '预警':
                            if each.is_warning == 1:
                                cabinet_dict['status'] = '报警'
                            if each.is_warning == 0:
                                cabinet_dict['status'] = '预警'
                    points_data.append(gradation_data)
                cabinet_dict['points'] = points_data
                data.append(cabinet_dict)
        return ret_res(code=0, data=data)


class CabinetDetailView(GenericAPIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        cabinet_id = request.query_params.get('cabinetId')
        point_type = request.query_params.get('pointType')
        if not point_type:
            point_type = TEMP_TYPE
        cabinet_dict = {}
        points = Point.objects.filter(cabinet__id=cabinet_id).filter(unit__type=point_type)
        gradations = points.values('gradation__id').annotate(count=Count('gradation__id'))
        cabinet = Cabinet.objects.filter(id=cabinet_id).first()
        cabinet_dict['cabinetName'] = cabinet.name
        cabinet_dict['cabinetId'] = cabinet.id
        cabinet_dict['warn_value'] = cabinet.warm_warning
        cabinet_dict['early_warn_value'] = cabinet.warm_early_warning
        cabinet_dict['status'] = '正常'
        points_data = []
        for gradation in gradations:
            gradation_id = gradation['gradation__id']
            gradation_new = Gradation.objects.filter(id=gradation_id).first()
            gradation_data = {'gradation': {'name': gradation_new.name, 'gradationId': gradation_id}}
            point = points.filter(gradation__id=gradation_id).all()
            for each in point:
                class_name = each.code[-1]
                gradation_data[class_name] = each.value
                if cabinet_dict['status'] == '正常' or cabinet_dict['status'] == '预警':
                    if each.is_warning == 1:
                        cabinet_dict['status'] = '报警'
                    if each.is_warning == 0:
                        cabinet_dict['status'] = '预警'
            points_data.append(gradation_data)
        cabinet_dict['data'] = points_data
        return ret_res(code=0, data=cabinet_dict)


class GradationCompareView(GenericAPIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        cabinet_id = request.query_params.get('cabinetId')
        point_type = request.query_params.get('pointType')
        if not point_type:
            point_type = TEMP_TYPE
        cabinet_dict = {}
        points = Point.objects.filter(cabinet=cabinet_id).filter(unit__type=point_type)
        gradations = points.values('gradation__id').annotate(count=Count('gradation__id'))
        y_bar = []
        x_bar = []
        count = 0
        for gradation in gradations:
            gradation_id = gradation['gradation__id']
            gradation_new = Gradation.objects.filter(id=gradation_id).first()
            gradation_data = {'gradation': gradation_new.name}
            point = points.filter(gradation__id=gradation_id).all()
            value_list = []
            if count > 0:
                for each in x_bar:
                    value_list.append(each)
            for each in point:
                class_name = each.code[-1]
                if count == 0:
                    x_bar.append(class_name)
                    value_list.append(each.value)
                else:
                    index = x_bar.index(class_name)
                    value_list[index] = each.value
            gradation_data['value'] = value_list
            count += 1
            y_bar.append(gradation_data)
        cabinet_dict['y_bar'] = y_bar
        cabinet_dict['x_bar'] = x_bar
        return ret_res(code=0, data=cabinet_dict)


class GradationView(GenericAPIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        cabinet_id = request.query_params.get('cabinetId')
        point_type = request.query_params.get('pointType')
        if not point_type:
            point_type = TEMP_TYPE
        data = []
        points = Point.objects.filter(cabinet=cabinet_id).filter(unit__type=point_type)
        gradations = points.values('gradation__id').annotate(count=Count('gradation__id'))
        for gradation in gradations:
            gradation_id = gradation['gradation__id']
            gradation_new = Gradation.objects.filter(id=gradation_id).first()
            gradation_data = {'gradation': gradation_new.name, 'gradationId': gradation_id}
            data.append(gradation_data)
        return ret_res(code=0, data=data)


class CompareABCView(GenericAPIView):
    permission_classes = [IsAuthenticated]

    def get(self, request, *args, **kwargs):
        cabinet_id = request.query_params.get('cabinetId')
        gradation_id = request.query_params.get('gradationId')
        point_type = request.query_params.get('pointType')
        start = request.query_params.get('startTime')
        end = request.query_params.get('endTime')
        if start:
            start = start + ' 00:00:00'
        if end:
            end = end + ' 23:59:59'
        if not start or not end:
            time_now = datetime.datetime.now()
            start = datetime.datetime(year=time_now.year, month=time_now.month, day=time_now.day, hour=0, minute=0, second=0)
            end = time_now
        if not point_type:
            point_type = TEMP_TYPE
        points = Point.objects.filter(cabinet=cabinet_id).filter(unit__type=point_type).filter(gradation=gradation_id).all()
        x_bar = []
        y_bar = []
        for point in points:
            name = point.name
            data = get_point_data(name, point.code, start, end)
            time_line = data['time']
            value_line = data['value']
            if len(time_line) > len(x_bar):
                x_bar = time_line
            point_dict = {'name': name, 'value': value_line}
            y_bar.append(point_dict)
        return ret_res(code=0, data={'x_bar': x_bar, 'y_bar': y_bar})


# 报警历史数据
class WarnHistoryLineView(GenericAPIView):
    queryset = Warn.objects.all()
    # permission_classes = [IsAuthenticated]
    # filter_backends = [DataLevelPermissionsFilter]
    permission_classes = []
    filter_backends = []
    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        start = request.query_params.get('startTime')
        end = request.query_params.get('endTime')
        point_code = request.query_params.get('pointCode')
        warn_type = request.query_params.get('warnType')
        if not start or not end:
            time = datetime.datetime.now()
            start = datetime.datetime(year=time.year, month=time.month, day=time.day, hour=0, minute=0, second=0)
            end = time
        else:
            start = datetime.datetime.strptime(start + ' 00:00:00', '%Y-%m-%d %H:%M:%S')
            end = datetime.datetime.strptime(end + ' 23:59:59', '%Y-%m-%d %H:%M:%S')
        warns = queryset.filter(create_datetime__gte=start).filter(point__code=point_code).\
            filter(type=warn_type).filter(create_datetime__lte=end).all()
        data = dict()
        time_list = []
        value_list = []
        for each in warns:
            time_list.append(datetime.datetime.strftime(each.create_datetime, '%Y-%m-%d %H:%M:%S'))
            value_list.append(each.value)
        data['time_list'] = time_list
        data['value_list'] = value_list
        return ret_res(code=0, data=data)


# 返回全部的报警记录
class WarnHistoryTableView(GenericAPIView):
    queryset = Warn.objects.all()
    # permission_classes = [IsAuthenticated]
    # filter_backends = [DataLevelPermissionsFilter]
    permission_classes = []
    filter_backends = []

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        page = request.query_params.get('page')
        limit = request.query_params.get('limit')
        point_type = request.query_params.get('pointType')
        if not point_type:
            point_type = TEMP_TYPE
        data = get_warn_and_early_warn(queryset, point_type, page, limit)
        return ret_res(code=0, data=data)


class VDetailView(GenericAPIView):
    queryset = Point.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        point_type = request.query_params.get('pointType')
        page = request.query_params.get('page')
        limit = request.query_params.get('limit')
        if not page:
            page = '1'
        if not limit:
            limit = '15'
        page = int(page)
        limit = int(limit)
        if point_type:
            pass
        else:
            point_type = VOLTAGE_TYPE
        total_point = queryset.filter(unit__type=point_type).all()
        points = queryset.filter(unit__type=point_type).order_by('value')[(page-1)*limit: page*limit]
        data = [
            {
                'pointName': point.name,
                'cabinetName': point.cabinet.name,
                'deptName': point.cabinet.dept.name,
                'value': point.value,
                'is_warning': point.is_warning,
                'updateTime': datetime.datetime.strftime(point.update_datetime, '%Y-%m-%d %H:%M:%S')
            }
            for point in points
        ]
        return ret_res(code=0, data={'total': len(total_point), 'data': data})


class IsHandelView(GenericAPIView):
    queryset = Warn.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        warn_id = request.query_params.get('warnId')
        warn = queryset.filter(id=warn_id)
        if warn:
            warn.update(**{'is_handel': True})
            point_id = warn.first().point.id
            queryset.filter(point__id=point_id).update(**{'is_handel': True})
            Point.objects.filter(id=point_id).update(**{'is_warning': 2})
            data = {'is_ok': True}
        else:
            data = {'is_ok': False}
        return ret_res(code=0, data=data)


class WarnEquipmentView(GenericAPIView):
    queryset = Warn.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        # 报警
        warn_queryset = queryset.filter(type=WARN_TYPE)
        is_not_handel = warn_queryset.filter(is_handel=False).all()
        data = {'is_ok': False}
        if is_not_handel:
            for each in is_not_handel:
                if each.point.is_warning == 1:
                    data = {'is_ok': True}
                else:
                    warn_id = each.id
                    queryset.filter(id=warn_id).update(**{'is_handel': True})
        # 预警
        early_warn = queryset.filter(type=EARLY_WARN_TYPE)
        is_not_handel_early = early_warn.filter(is_handel=False).all()
        if is_not_handel_early:
            for each in is_not_handel_early:
                if each.point.is_warning == 0:
                    continue
                else:
                    warn_id = each.id
                    queryset.filter(id=warn_id).update(**{'is_handel': True})
        return ret_res(code=0, data=data)


class AppletCabinetView(GenericAPIView):
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]
    queryset = Cabinet.objects.all()

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        point_type = request.query_params.get('pointType')
        page = request.query_params.get('page')
        limit = request.query_params.get('limit')
        if not point_type:
            point_type = TEMP_TYPE
        if limit and page:
            limit = int(limit)
            page = int(page)
        if not limit or not page:
            page = 1
            limit = 3
        count = queryset.filter().all().count()
        cabinets = queryset.filter().all()[(page-1)*limit:page*limit]
        data = []
        for cabinet in cabinets:
            cabinet_dict = {}
            points_data = []
            cabinet_dict['cabinetName'] = cabinet.name
            cabinet_dict['cabinetId'] = cabinet.id
            cabinet_dict['warn_value'] = cabinet.warm_warning
            cabinet_dict['early_warn_value'] = cabinet.warm_early_warning
            cabinet_dict['status'] = '正常'
            points = Point.objects.filter(cabinet=cabinet.id).filter(unit__type=point_type).order_by('gradation__id')
            gradations = points.values('gradation__name').annotate(count=Count('gradation__name'))
            for gradation in gradations:
                gradation_name = gradation['gradation__name']
                gradation_data = {'gradation': gradation_name}
                point = points.filter(gradation__name=gradation_name).all()
                for each in point:
                    class_name = each.code[-1]
                    gradation_data[class_name] = each.value
                    if cabinet_dict['status'] == '正常' or cabinet_dict['status'] == '预警':
                        if each.is_warning == 1:
                            cabinet_dict['status'] = '报警'
                        if each.is_warning == 0:
                            cabinet_dict['status'] = '预警'
                points_data.append(gradation_data)
            cabinet_dict['points'] = points_data
            data.append(cabinet_dict)
        return ret_res(code=0, data={'total': count, 'data': data})


class AppletWarnNowViews(GenericAPIView):
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]
    queryset = Point.objects.all()

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset()).filter(is_warning=WARN_TYPE).filter(unit__type=TEMP_TYPE)
        data = [applet_warning(each.id) for each in queryset]
        return ret_res(code=0, data=data)


class AppletWarnHistoryTableView(GenericAPIView):
    queryset = Warn.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        page = request.query_params.get('page')
        limit = request.query_params.get('limit')
        dept_id = request.query_params.get('deptId')
        queryset = queryset.filter(point__cabinet__dept__id=dept_id)
        start = request.query_params.get('startTime')
        end = request.query_params.get('endTime')
        if not start:
            return ret_res(code=202, data={})
        if not end:
            return ret_res(code=203, data={})
        data = get_warn(queryset, TEMP_TYPE, WARN_TYPE, page, limit, start, end)
        return ret_res(code=0, data=data)


# 导出文件
class WarnToExcel(GenericAPIView):
    # 查询全部的告警表
    queryset = Warn.objects.all()
    # 该视图需要登录
    permission_classes = [IsAuthenticated]
    # 应用数据级别的权限过滤器，限制用户只能访问有权限的数据。
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        # 时间范围的开始和结束
        start = request.query_params.get('startTime')
        end = request.query_params.get('endTime')
        # 点位编码和告警类型
        point_code = request.query_params.get('pointCode')
        warn_type = request.query_params.get('warnType')

        if not start or not end:
            #
            time = datetime.datetime.now()
            start = datetime.datetime(year=time.year, month=time.month, day=time.day, hour=0, minute=0, second=0)
            end = time
        else:
            #
            start = datetime.datetime.strptime(start + ' 00:00:00', '%Y-%m-%d %H:%M:%S')
            end = datetime.datetime.strptime(end + ' 23:59:59', '%Y-%m-%d %H:%M:%S')
        #     获取告警信息
        warns = queryset.filter(create_datetime__gte=start).filter(point__code=point_code). \
            filter(type=warn_type).filter(create_datetime__lte=end).all()
        # 构建data字典和空的报警信息列表
        data = dict()
        time_list = []
        value_list = []
        cabinet_list = []
        point_list = []
        if len(warns) == 0:
            time_list = ['空']
            value_list = ['空']
            cabinet_list = ['空']
            point_list = ['空']
        else:
            # 如果报警信息不为空 遍历插入到
            for each in warns:
                time_list.append(datetime.datetime.strftime(each.create_datetime, '%Y-%m-%d %H:%M:%S'))
                value_list.append(each.value)
                point_list.append(each.point.name)
                cabinet_list.append(each.point.cabinet.name)
        data['传感器'] = point_list
        data['配电站'] = cabinet_list
        data['值'] = value_list
        data['时间'] = time_list
        # 生成excel文件
        dataframe_data = pd.DataFrame(data)
        #创建一个内存中的字节流对象 output，用于存储生成的 Excel 文件
        output = io.BytesIO()
        dataframe_data.to_excel(output, index=False)
        # 将文件指针移动到开头，准备输出数据
        output.seek(0)
        response = HttpResponse()
        response["Content-Type"] = "application/vnd.ms-excel"
        response['Content-Disposition'] = 'attachment;filename= '+'报警'.encode('utf-8').decode('ISO-8859-1')+'.xlsx'
        # 把文件响应回去
        response.write(output.getvalue())
        output.close()
        return response


class RoleView(GenericAPIView):
    queryset = Role.objects.all()
    permission_classes = []
    authentication_classes = []

    def get(self, request, *args, **kwargs):
        queryset = self.queryset.filter(admin=False).all()
        data = [
            {
                'name': each.name,
                'roleId': each.id
            }
            for each in queryset
        ]
        return ret_res(code=0, data=data)


from dvadmin.system.models import Users


class DeptView(GenericAPIView):
    """部门菜单"""
    queryset = Dept.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        depts = queryset.filter(parent__parent__isnull=False)
        data = []
        for each in depts:
            data.append(
                {
                    'name': each.name,
                    'id': each.id
                }
            )
        return ret_res(200, data)


class CreateUserView(GenericAPIView):
    queryset = Users.objects.all()
    permission_classes = []
    authentication_classes = []

    def post(self, request, *args, **kwargs):
        name = request.data.get('name')
        username = request.data.get('username')
        dept_id = request.data.get('deptId')
        # role_id = request.data.get('roleId')
        password = request.data.get('password')
        print(name)
        if not name or not username or not dept_id or not password:
            return ret_res(code=-1)
        # role = Role.objects.filter(id=role_id).first()
        role_id = Role.objects.filter(key='guanxian_admin').first().id
        dept = Dept.objects.filter(id=dept_id).first()
        user = Users.objects.create(dept=dept, **{'name': name, 'username': username, 'password': password})
        user.role.add(role_id)
        user.save()
        return ret_res(code=0)


class UpdateUserView(GenericAPIView):
    queryset = Users.objects.all()
    permission_classes = []
    authentication_classes = []

    def post(self, request, *args, **kwargs):
        user_id = request.data.get('id')
        name = request.data.get('name')
        username = request.data.get('username')
        dept_id = request.data.get('deptId')
        if not user_id:
            return ret_res(code=-1)
        dept = Dept.objects.filter(id=dept_id).first()
        Users.objects.filter(id=user_id).update(dept=dept, **{'name': name, 'username': username})
        return ret_res(code=0)


class VDeviceListView(GenericAPIView):
    """能源设备列表"""
    queryset = Point.objects.all()
    permission_classes = [IsAuthenticated]
    filter_backends = [DataLevelPermissionsFilter]

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        dept_id = request.query_params.get('dept_id')
        device_list = []
        result = []
        v_devices = queryset.filter(description=DESCRIPOTION)
        if dept_id:
           v_devices = v_devices.filter(cabinet__dept__id=dept_id).order_by('cabinet__id')
        for device in v_devices:
            dept_name = device.cabinet.dept.name
            if dept_name not in device_list:
                device_list.append(dept_name)
                result.append({'dept_name': dept_name, 'devices_data': [{
                    'device_name': device.cabinet.name,
                    'device_value': device.value,
                    'device_id': device.cabinet.id
                }]})
            else:
                device_index = device_list.index(dept_name)
                result[device_index]['devices_data'].append({
                    'device_name': device.cabinet.name,
                    'device_value': device.value,
                    'device_id': device.cabinet.id
                })
        return DetailResponse(result)


class DeviceEnergyDetailView(GenericAPIView):
    """设备能耗本日趋势"""
    queryset = Point.objects.all()
    permission_classes = [IsAuthenticated]

    def get(self, *args, **kwargs):
        device_id = self.request.query_params.get('device_id', None)
        table = self.request.query_params.get('table', 'false')
        data = {}
        if device_id:
            queryset: Point = self.get_queryset().filter(cabinet__id=device_id, description=DESCRIPOTION).first()
            if queryset:
                pool = load_tdengine_pool()
                point_code = queryset.code
                cabinet_name = queryset.cabinet.name
                try:
                    end_time = datetime.datetime.now()
                    start_time = str(end_time)[:10] + ' 00:00:00'
                    with pool.get() as cur:
                        start_sql = f'select first(value) from {point_code} where ts>="{start_time}" interval(1h)'
                        cur.execute(start_sql)
                        start_data = cur.fetchall()
                        if start_data:
                            end_sql = f'select last(value) from {point_code} where ts>="{start_time}" interval (1h)'
                            cur.execute(end_sql)
                            end_data = cur.fetchall()
                            start_pd_data = pd.DataFrame(start_data)
                            start_pd_data.columns = ['ts', 'first_value']
                            end_pd_data = pd.DataFrame(end_data)
                            end_pd_data.columns = ['ts', 'last_value']
                            result_pd = pd.merge(start_pd_data, end_pd_data, how='inner', on='ts')
                            result_pd['ele_count'] = result_pd['last_value'] - result_pd['first_value']
                            result_pd['ele_count'] = result_pd['ele_count'].apply(lambda x: round(x, 2))
                            result_pd['ts'] = result_pd['ts'].apply(lambda x: str(x)[:19])
                            if table == 'true':
                                result_pd['unit'] = queryset.unit.code
                                result_pd['device_name'] = cabinet_name
                                data['table_data'] = result_pd.to_dict('records')
                            else:
                                data['sum'] = round(result_pd['ele_count'].sum(), 2)
                                data['unit'] = queryset.unit.code
                                data['line_data'] = {'x_list': result_pd['ts'].tolist(),
                                                     'y_list': result_pd['ele_count'].tolist()}
                except:
                    time_list = []
                    count_list = []
                    unit_list = []
                    cabinet_name_list = []
                    time_now = datetime.datetime.now()
                    start_time = datetime.datetime(year=time_now.year, month=time_now.month, day=time_now.day, hour=0, minute=0, second=0)
                    time_hour = time_now.hour - 1
                    unit = queryset.unit.code
                    for each in range(0, time_hour):
                        time_list.append(start_time + datetime.timedelta(hours=each))
                        count_list.append(0)
                        unit_list.append(unit)
                        cabinet_name_list.append(cabinet_name)
                    result_pd = pd.DataFrame({'ele_count': count_list, 'ts': time_list,
                                              'unit': unit_list, 'device_name': cabinet_name_list})
                    result_pd['ts'] = result_pd['ts'].apply(lambda x: str(x)[:19])
                    if table == 'true':
                        result_pd['unit'] = queryset.unit.code
                        result_pd['device_name'] = cabinet_name
                        data['table_data'] = result_pd.to_dict('records')
                    else:
                        data['sum'] = round(result_pd['ele_count'].sum(), 2)
                        data['unit'] = queryset.unit.code
                        data['line_data'] = {'x_list': result_pd['ts'].tolist(),
                                             'y_list': result_pd['ele_count'].tolist()}
        return DetailResponse(data)


class EnergyTimeView(GenericAPIView):
    """时间维度"""
    permission_classes = []
    authentication_classes = []

    def get(self, *args, **kwargs):
        data = [{'name': '月', 'value': '1n'}, {'name': '日', 'value': '1d'}]
        return DetailResponse(data)


class ELEDeviceDetailView(GenericAPIView):
    """设备能耗本日趋势"""
    queryset = Point.objects.all()
    # permission_classes = [IsAuthenticated]
    permission_classes = []
    authentication_classes = []

    def get(self, *args, **kwargs):
        device_id = self.request.query_params.get('device_id', None)
        interval = self.request.query_params.get('interval', '1n')
        time = self.request.query_params.get('time', None)
        table = self.request.query_params.get('table', 'false')
        data = {}
        if device_id and interval and time:
            if len(time) == 4:
                start_time = time + '-01-01 00:00:00'
                end_time = str(int(time) + 1) + '-01-01 00:00:00'
            else:
                start_time = time + '-01 00:00:00'
                year = int(time.split('-')[0])
                month = int(time.split('-')[1])
                if month < 12:
                    end_time = str(year) + '-' + str(month+1) + '-01 00:00:00'
                else:
                    end_time = str(year + 1) + '-01-01 00:00:00'
            queryset: Point = self.get_queryset().filter(cabinet__id=device_id, description=DESCRIPOTION).first()
            if queryset:
                pool = load_tdengine_pool()
                point_code = queryset.code
                cabinet_name = queryset.cabinet.name
                try:
                    with pool.get() as cur:
                        start_sql = f'select first(value) from {point_code} where ts>="{start_time}" and ts<"{end_time}" interval({interval})'
                        cur.execute(start_sql)
                        start_data = cur.fetchall()
                        if start_data:
                            end_sql = f'select last(value) from {point_code} where ts>="{start_time}" and ts<="{end_time}" interval({interval})'
                            cur.execute(end_sql)
                            end_data = cur.fetchall()
                            start_pd_data = pd.DataFrame(start_data)
                            start_pd_data.columns = ['ts', 'first_value']
                            end_pd_data = pd.DataFrame(end_data)
                            end_pd_data.columns = ['ts', 'last_value']
                            result_pd = pd.merge(start_pd_data, end_pd_data, how='inner', on='ts')
                            result_pd['ele_count'] = result_pd['last_value'] - result_pd['first_value']
                            result_pd['ele_count'] = result_pd['ele_count'].apply(lambda x: round(x, 2))
                            if interval == '1n':
                                result_pd['ts'] = result_pd['ts'].apply(lambda x: str(x)[:7])
                                result_pd['time_des'] = '月'
                            else:
                                result_pd['ts'] = result_pd['ts'].apply(lambda x: str(x)[:10])
                                result_pd['time_des'] = '日'
                            if table == 'true':
                                result_pd['unit'] = queryset.unit.code
                                result_pd['device_name'] = cabinet_name
                                data['table_data'] = result_pd.to_dict('records')
                            else:
                                data['sum'] = round(result_pd['ele_count'].sum(), 2)
                                data['unit'] = queryset.unit.code
                                data['line_data'] = {'x_list': result_pd['ts'].tolist(),
                                                     'y_list': result_pd['ele_count'].tolist()}
                                logger.info(data)
                except:
                    time_list = []
                    count_list = []
                    unit_list = []
                    cabinet_name_list = []
                    time_now = datetime.datetime.now()
                    unit = queryset.unit.code
                    if interval == '1n':
                        time_month = time_now.month + 1
                        for each in range(1, time_month):
                            time_list.append(datetime.datetime(year=time_now.year, month=each, day=1, hour=0, minute=0, second=0))
                            count_list.append(0)
                            unit_list.append(unit)
                            cabinet_name_list.append(cabinet_name)
                    else:
                        time_day = time_now.day + 1
                        for each in range(1, time_day):
                            time_list.append(
                                datetime.datetime(year=time_now.year, month=time_now.month, day=each, hour=0, minute=0, second=0))
                            count_list.append(0)
                            unit_list.append(unit)
                            cabinet_name_list.append(cabinet_name)
                    result_pd = pd.DataFrame({'ele_count': count_list, 'ts': time_list,
                                              'unit': unit_list, 'device_name': cabinet_name_list})
                    if interval == '1n':
                        result_pd['ts'] = result_pd['ts'].apply(lambda x: str(x)[:7])
                        result_pd['time_des'] = '月'
                    else:
                        result_pd['ts'] = result_pd['ts'].apply(lambda x: str(x)[:10])
                        result_pd['time_des'] = '日'
                    result_pd['last_value'] = 0
                    result_pd['first_value'] = 0
                    if table == 'true':
                        result_pd['unit'] = queryset.unit.code
                        result_pd['device_name'] = cabinet_name
                        data['table_data'] = result_pd.to_dict('records')
                    else:
                        data['sum'] = round(result_pd['ele_count'].sum(), 2)
                        data['unit'] = queryset.unit.code
                        data['line_data'] = {'x_list': result_pd['ts'].tolist(),
                                             'y_list': result_pd['ele_count'].tolist()}
        return DetailResponse(data)



class test(GenericAPIView):
    queryset = Cabinet.objects.all()
    permission_classes = []
    authentication_classes = []

    def get(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())
        # print(queryset)
        # 每次过来只有一个部门
        dept_id = request.query_params.get('deptId')
        print(dept_id)

        #　获取用户输入的开始时间和结束时间以及pointCode,pointCode
        start = request.query_params.get('startTime')
        end = request.query_params.get('endTime')
        dt_object = datetime.datetime.fromisoformat(start)
        formatted_time_str = dt_object.strftime("%Y-%m-%d %H:%M:%S")
        # print(formatted_time_str)
        dt_object1 = datetime.datetime.fromisoformat(end)
        formatted_time_str1 = dt_object1.strftime("%Y-%m-%d %H:%M:%S")
        # print(formatted_time_str1)

        depts = Dept.objects.filter(id=dept_id).first()
        cabinets = queryset.filter(dept__id=dept_id).order_by('create_datetime')
        data = []


# ----------------------------------------第一个for循环3次(cabinet_dict字典存入)--------------------------------------
        for cabinet in cabinets:          # 一共三个分区所

            cabinet_dict = {}  # 部门和电柜数据
            cabinet_dict['deptName'] = depts.name
            cabinet_dict['cabinetName'] = cabinet.name
            cabinet_dict['cabinetId'] = cabinet.id
            cabinet_dict['warn_value'] = cabinet.warm_warning
            cabinet_dict['early_warn_value'] = cabinet.warm_early_warning

            # cabinet_dict['status'] = '正常'

            points = (Point.objects.filter(cabinet_id=cabinet.id)
                      .order_by('gradation__id'))
            datass = []
# -------------------------------第二个for循环2次（点位表数据，放入datass中）——————————————————————————————————————
            for point1 in points:   # 一个分区所下面对应2个点位（可能是温度也可能是湿度）
                if point1:
                    dict1 = {}
                    dict1["gradation"] = point1.gradation.name
                    # datass.append(point1.gradation.name)  # 确保gradation.name正确
                    # # 报警预警
                    # if(point1.is_warning==0):
                    #     cabinet_dict['status'] = '预警'
                    # elif(point1.is_warning==1):
                    #     cabinet_dict['status'] = '报警'
                    # else:
                    #     cabinet_dict['status'] = '正常'

                    # 拿到对应的point_code，也就是子表名称
                    table = point1.code
                    # print(table)

                    with load_tdengine_pool().get() as cursor:  # 对应着一个点位的所有数据（温度湿度）
                        sql = f"SELECT * FROM {table} WHERE ts > '{formatted_time_str}' AND ts < '{formatted_time_str1}' ORDER BY ts ASC;"

                        cursor.execute(sql)

                        result = cursor.fetchall()
                        # print(result)
                        datas = []
# -——————————————————————————————————————第三次for循环（对应的值，存入datas列表中）————————————————————————————————————————
                        for record in result:
                            dataes = {}
                            record_time, value = record
                            rounded_number = round(value, 2)
                            formatted_time_str2 = record_time.strftime("%Y-%m-%d %H:%M:%S")
                            dataes['value'] = rounded_number
                            dataes['time'] = formatted_time_str2


                            # 将taos查出来的真是数据放入对应列表datas
                            datas.append(dataes)
                        # print(datas)
                    dict1['value_time'] = datas
                    datass.append(dict1)
            cabinet_dict['gradation_value_time'] = datass

            data.append(cabinet_dict)

        return ret_res(code=0, data=data)